package cn.virens.common.boot.filter.logging;

import cn.virens.common.spring.bean.SpringBeanProxy;
import cn.virens.common.spring.filter.AbstractPathMatcherFilter;
import cn.virens.common.util.exception.APIException;
import cn.virens.common.util.exception.ExceptionUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.io.IOException;
import java.nio.charset.Charset;

public class SimpleHandlerLoggingFilter extends AbstractPathMatcherFilter implements ApplicationContextAware {
    private SimpleHandlerLoggingProvider provider;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        SimpleHandlerLoggingRequest loggingRequest = new SimpleHandlerLoggingRequest(request);

        try {
            filterChain.doFilter(loggingRequest, response);

            this.logInfo(loggingRequest, null);
        } catch (Exception e) {
            this.logError(loggingRequest, e);

            throw e;
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.provider = SpringBeanProxy.proxy(SimpleHandlerLoggingProvider.class, applicationContext);
    }

    protected void logError(SimpleHandlerLoggingRequest request, Exception e) throws APIException {
        this.provider.error(request, createMessage(request, ExceptionUtil.c(e)));
    }

    protected void logInfo(SimpleHandlerLoggingRequest request, Exception e) throws APIException {
        this.provider.info(request, createMessage(request, "SUCCESS"));
    }

    /**
     * 创建日志消息主题
     */
    protected String createMessage(SimpleHandlerLoggingRequest request, String ex) {
        StringBuilder msg = new StringBuilder(ex);
        msg.append(' ').append(request.getMethod());

        msg.append(", requestURI=").append(request.getRequestURI());
        msg.append(", query=").append(request.getQueryString());
        msg.append(", payload=").append(getPayload(request));

        return msg.toString();
    }

    /**
     * 获取POST请求中的请求内容
     */
    protected String getPayload(SimpleHandlerLoggingRequest request) {
        byte[] payload = request.getCacheAsByteArray();
        if (payload != null && payload.length > 0) {
            Charset c = request.getCharacter();

            return StrUtil.str(payload, c);
        }

        return "";
    }
}
